/**
 * 处理视图相关操作的控制器
 * 接受包，并分配线程组装包，直到获取组合后的屏幕Icon图像
 */
package com.jahentao.integrationTest.case03.common;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import javax.swing.Icon;

import com.jahentao.integrationTest.case03.client.CombineScreenThread;


/**
 * @author jahen
 * @date 2016年8月6日
 * @time 下午11:23:32
 * @category Socket编程
 */
public class ScreenHandler extends Thread{
	private Map<Long,CombineScreenThread> threadMap;
	private Queue<Icon> frameQueue; // 画面帧队列
	@SuppressWarnings("unused")
	private long earliestTime;
	
	private static ScreenHandler instance;
	private DatagramSocket receiver;
	private byte[] buffer;
	
	public Map<Long, CombineScreenThread> getThreadMap() {
		return threadMap;
	}
	public Queue<Icon> getFrameQueue() {
		return frameQueue;
	}

	public static ScreenHandler getScreenHandlerInstance() {
		if(instance==null)
			instance = new ScreenHandler();
		return instance;
	}
	
	private ScreenHandler() {
		threadMap = new HashMap<Long, CombineScreenThread>();
		frameQueue = new ConcurrentLinkedQueue<Icon>();
		buffer = new byte[1024 * 64];
	}
	
	@Override
	public void run() {
		try {
			receiver = new DatagramSocket(8888);
			while(true){
				DatagramPacket p = new DatagramPacket(buffer , buffer.length);
				receiver.receive(p);
				byte[] unWrapingData = p.getData(); // 拆包后得到的数据
				
				long time  = readLong(unWrapingData,0);
				int packetNum = readInt(unWrapingData,8);
				int order = readInt(unWrapingData,12);
				int dataLen = readInt(unWrapingData,16);
				byte[] data = Arrays.copyOfRange(unWrapingData, 20, dataLen+20);
				Packet packet = new Packet(time, packetNum, order, data); // 组装数据 成逻辑上的概念Packet
				
				CombineScreenThread combineThread;
				if((combineThread = threadMap.get(time))==null){
					combineThread = new CombineScreenThread(time, packetNum, this);
					combineThread.start();
					threadMap.put(time, combineThread);
				}
				
				combineThread.add(packet); // 添加包
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 读取一个整数<br>
	 * 从offset处开始读4个字节， high bytes first 大端模式
	 */
	private int readInt(byte[] data, int offset) {
		return (data[offset]<<24 & 0xff000000) |
				(data[offset+1]<<16 & 0xff0000) |
				(data[offset+2]<<8 & 0xff00) |
				(data[offset+3] & 0xff);
	}

	/**
	 * 读取一个长整数<br>
	 * 从offset处开始读8个字节， high bytes first 大端模式
	 */
	private long readLong(byte[] data, int offset) {
		long result = 0;
		long[] l = {0xff00000000000000L, 0xff000000000000L, 0xff0000000000L, 0xff00000000L,	0xff000000, 0xff0000, 0xff00, 0xff};
		for(int i=0; i<8; i++){
			result |= ((long)data[offset+i] << ((7-i)*8)) & l[i];
		}
		return result;
	}

	/**
	 * 获取下一帧，加同步锁
	 */
	public synchronized Icon getNextFrame() {
		Icon icon = null;
		if(!frameQueue.isEmpty()) {
				icon = frameQueue.remove();
		}
		return icon;
	}
	
}
